#pragma once

#include"Common.h"

#include"Location.h"
#include"Command.h"
#include"Calculate.h"
#include"PlayerUnitTypeData.h"

namespace Custom
{
	class Unit
	{
	public:
		PlayerEnum Owner;
		Location Position;
		float FacingAngle;
		int AttackCoolDown;
		bool IsAttackFrame;
		BWAPI::UnitType Type;
		BWAPI::Unit* RealUnitPointer;
		Command CurrentCommand;
		bool IsIdle;
		bool NeedToCheckNearUnits;
		int arrivalCountDown;
		//--
		Unit()
		{
		}
		Unit(BWAPI::Unit* unit)
			:Owner(unit->getPlayer() == Broodwar->self() ? Self : Enemy),
			_hp(unit->getHitPoints()),
			_shield(unit->getShields()),
			Position(unit->getPosition().x() , unit->getPosition().y()),
			FacingAngle(unit->getAngle()),
			AttackCoolDown(unit->getGroundWeaponCooldown()),
			IsAttackFrame(unit->isAttackFrame()),
			Type(unit->getType()),
			RealUnitPointer(unit),
			arrivalCountDown(0),
			IsIdle(true),
			NeedToCheckNearUnits(false)
		{
		}
		void IssueCommand(const Command& command)
		{
			if(Alive())
			{
				CurrentCommand = command;
				IsIdle = false;
				if(command.Type == Command::Move)
				{
					arrivalCountDown = command.TargetPosition.GetDistance(Position) / PlayerUnitTypeInfo.GetTopSpeed(Owner , Type);
				}
			}
		}
		float GetX() const
		{
			return Position.X;
		}
		float GetY() const
		{
			return Position.Y;
		}
		bool Alive() const
		{
			return _hp > 0;
		}
		int Hp() const
		{
			return _hp + _shield;
		}
		void DamageTarget(Custom::Unit* target)
		{
			float damage(Type.groundWeapon().damageAmount());
			float factor(1.0f);
			//--
			if(Type.groundWeapon().damageType() == DamageTypes::Normal)
			{
			}
			else if(Type.groundWeapon().damageType() == DamageTypes::Explosive)
			{
				if(target->Type.size() == UnitSizeTypes::Small)
				{
					factor = 0.5f;
				}
				else if(target->Type.size() == UnitSizeTypes::Medium)
				{
					factor = 0.75f;
				}
			}
			else if(Type.groundWeapon().damageType() == DamageTypes::Concussive)
			{
				if(target->Type.size() == UnitSizeTypes::Large)
				{
					factor = 0.25f;
				}
				else if(target->Type.size() == UnitSizeTypes::Medium)
				{
					factor = 0.5f;
				}
			}
			
			for(int whichHit = 0 ; whichHit < Type.maxGroundHits() ; ++whichHit)
			{
				if(target->_shield > 0)
				{
					target->_shield -= damage;
					if(target->_shield < 0)
					{
						float damageLeft = -target->_shield;
						target->_shield = 0;
						target->_hp -= damageLeft * factor - target->Type.armor();
					}
				}
				else
				{
					target->_hp -= damage * factor - target->Type.armor();
				}
			}
			if(target->_hp < 0)
			{
				target->_hp = 0;
			}
		}
	private:
		int _hp;
		int _shield;
	};
}